package com.txtdhis.consumer.config.shiro;

import com.txtdhis.common.util.Constant;
import com.txtdhis.common.util.StringUtil;
import com.txtdhis.consumer.config.shiro.jwt.*;
import com.txtdhis.consumer.util.JedisUtil;
import com.txtdhis.consumer.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.Set;

/**
 * 自定义Realm
 * @author
 * @date 2018/8/30 14:10
 */
@Service
@Slf4j
public class UserRealm extends AuthorizingRealm {


    /**
     * 大坑，必须重写此方法，不然Shiro会报错
     */
    @Override
    public boolean supports(AuthenticationToken authenticationToken) {
        return authenticationToken instanceof JwtToken;
    }

    /**
     * 只有当需要检测用户权限的时候才会调用此方法，例如checkRole,checkPermission之类的
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
 //       SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
//        String username = JwtUtil.getClaim(principalCollection.toString(), Constant.ACCOUNT);
//        UserDto userDto = new UserDto();
//        userDto.setAccount(account);
//        // 查询用户角色
//        List<RoleDto> roleDtos = roleMapper.findRoleByUser(userDto);
//        for (RoleDto roleDto : roleDtos) {
//            if (roleDto != null) {
//                // 添加角色
//                simpleAuthorizationInfo.addRole(roleDto.getName());
//                // 根据用户角色查询权限
//                List<PermissionDto> permissionDtos = permissionMapper.findPermissionByRole(roleDto);
//                for (PermissionDto permissionDto : permissionDtos) {
//                    if (permissionDto != null) {
//                        // 添加权限
//                        simpleAuthorizationInfo.addStringPermission(permissionDto.getPerCode());
//                    }
//                }
//            }
//        }
//                 return simpleAuthorizationInfo;
        String username = JwtUtil.getClaim(principalCollection.toString(), Constant.ACCOUNT);
        SimpleAuthorizationInfo info= new SimpleAuthorizationInfo();

        log.info(principalCollection.toString());
        //log.info(principalCollection.getPrimaryPrincipal().toString());
        //正确的业务流程是到数据库拿该用户的权限再去进行授权的，这里只是简单的直接授权
        if (username.equals("admin")){
            Set<String> role=new HashSet<>();
            role.add("admin");

            info.setRoles(role);
            info.addStringPermission("user:view");
            info.addStringPermission("user:edit");
        }else {
            Set<String> role=new HashSet<>();
            role.add("user");
            info.setRoles(role);
        }
        return info;

    }

    /**
     * 默认使用此方法进行用户名正确与否验证，错误抛出异常即可。
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//        String token = (String) authenticationToken.getCredentials();
//        // 解密获得account，用于和数据库进行对比
//        String account = JwtUtil.getClaim(token, Constant.ACCOUNT);
//        // 帐号为空
//        if (StringUtil.isBlank(account)) {
//            throw new AuthenticationException("Token中帐号为空(The account in Token is empty.)");
//        }
//        // 查询用户是否存在
//        UserDto userDto = new UserDto();
//        userDto.setAccount(account);
//        userDto = userMapper.selectOne(userDto);
//        if (userDto == null) {
//            throw new AuthenticationException("该帐号不存在(The account does not exist.)");
//        }
//        // 开始认证，要AccessToken认证通过，且Redis中存在RefreshToken，且两个Token时间戳一致
//        if (JwtUtil.verify(token) && JedisUtil.exists(Constant.PREFIX_SHIRO_REFRESH_TOKEN + account)) {
//            // 获取RefreshToken的时间戳
//            String currentTimeMillisRedis = JedisUtil.getObject(Constant.PREFIX_SHIRO_REFRESH_TOKEN + account).toString();
//            // 获取AccessToken时间戳，与RefreshToken的时间戳对比
//            if (JwtUtil.getClaim(token, Constant.CURRENT_TIME_MILLIS).equals(currentTimeMillisRedis)) {
//                return new SimpleAuthenticationInfo(token, token, "userRealm");
//            }
//        }
//        throw new AuthenticationException("Token已过期(Token expired or incorrect.)");

         String token = (String) authenticationToken.getCredentials();
        // 解密获得account，用于和数据库进行对比
        String account = JwtUtil.getClaim(token, Constant.ACCOUNT);
        // 帐号为空
        if (StringUtil.isBlank(account)) {
            throw new AuthenticationException("Token中帐号为空(The account in Token is empty.)");
        }
        System.out.println("身份认证");

        String username= JwtUtil.getClaim(token, Constant.ACCOUNT);
        System.out.println(username);
        //这里要去数据库查找是否存在该用户，这里直接放行
        if (username==null){
            throw new AuthenticationException("认证失败！");
        }
                // 开始认证，要AccessToken认证通过，且Redis中存在RefreshToken，且两个Token时间戳一致
        if (JwtUtil.verify(token) && JedisUtil.exists(Constant.PREFIX_SHIRO_REFRESH_TOKEN + account)) {
            // 获取RefreshToken的时间戳
            String currentTimeMillisRedis = JedisUtil.getObject(Constant.PREFIX_SHIRO_REFRESH_TOKEN + account).toString();
            // 获取AccessToken时间戳，与RefreshToken的时间戳对比
            if (JwtUtil.getClaim(token, Constant.CURRENT_TIME_MILLIS).equals(currentTimeMillisRedis)) {
                return new SimpleAuthenticationInfo(token, token, "userRealm");
            }
        }
        throw new AuthenticationException("Token已过期(Token expired or incorrect.)");
    }
}
